﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//添加关联脚本  
[RequireComponent(typeof(CarControl))]
public class CarAIControl : MonoBehaviour {


    [SerializeField]
    private float m_SteerSensitivity = 0.05f;                                // 人工智能如何敏感地使用转向输入转向所需的方向  
      
    [SerializeField]
    private float m_AccelSensitivity = 0.04f;                                // 人工智能如何敏感地使用加速器达到当前期望的速度 
    [SerializeField]
    private float m_BrakeSensitivity = 1f;                                   // 人工智能是如何敏感地使用刹车达到当前期望的速度 
    [SerializeField]
    private float m_LateralWanderDistance = 3f;                              // 汽车会向它的目标横向移动多远   
    [SerializeField]
    private float m_LateralWanderSpeed = 0.1f;                               // 横向漫游的波动速度有多快 
    [SerializeField]
    [Range(0, 1)]
    private float m_AccelWanderAmount = 0.1f;                  // 汽车的漫游速度
    //汽车加速移动会有多少波动  
    [SerializeField]
    private float m_AccelWanderSpeed = 0.1f;                                 // 汽车加速漂移的速度有多快 
    //AI在加速制动时应该考虑什么  
    [SerializeField]
    public bool m_Driving;                                                  // ai目前是主动行驶还是停止。  
    //目标地点  
    [SerializeField]
    private Transform m_Target;                                              // 目标对象  
    //会在接近目标的时候停止行驶？  
    [SerializeField]
    private bool m_StopWhenTargetReached;                                    // 我们到达目标后应该停止开车吗？
    //接近目标考虑我们'到达'，并停止驾驶。  
    [SerializeField]
    private float m_ReachTargetThreshold = 2;                                // 离目标很近，认为我们已经“到达”了，并且停止了驾驶。
 

    //一个随机值的汽车基地徘徊（使AI汽车不都徘徊在同一模式）  
    private float m_RandomPerlin;             // 一个随机的值，让汽车以其漫游为基础
    private CarControl m_CarController;    // 汽车控制器
    private Rigidbody m_Rigidbody;

    private void Awake()
    {
        m_CarController = GetComponent<CarControl>();

        m_RandomPerlin = Random.value * 100;

        m_Rigidbody = GetComponent<Rigidbody>();
    }

    //void Start()  
    //{  
    //    cube = gameObject.GetComponent<NavMeshAgent>();  

    //}  

    //// Update is called once per frame    
    //void Update()  
    //{  
    //    cube.SetDestination(m_Target.position);  
    //}  

    private void FixedUpdate()
    {


        //foreach (Transform m_target in m_Target)  
        //    {  

        //}  
        //如果没有目标或者没有行驶，不move，否则朝着目标行驶  
        if (m_Target == null || !m_Driving)
        {
            // Car should not be moving,  
            // use handbrake to stop  
            m_CarController.Move(0, 0, -1f, 1f);
        }
        else
        {
            m_CarController.AccelInput = 1.0f;
            Vector3 fwd = transform.forward;
            //如果实际速度大于最大速度的1/10  
            if (m_Rigidbody.velocity.magnitude > m_CarController.MaxSpeed * 0.1f)
            {
                fwd = m_Rigidbody.velocity;
            }

            float desiredSpeed = m_CarController.MaxSpeed;

            // 与其他车辆相撞引起的避让动作：  

            Vector3 offsetTargetPos = m_Target.position;
              //车辆漫游到目标的路径，左右抖动。  
            offsetTargetPos += m_Target.right *
                (Mathf.PerlinNoise(Time.time * m_LateralWanderSpeed, m_RandomPerlin) * 2 - 1) *
                m_LateralWanderDistance;

            // 根据加速或刹车的不同使用不同的敏感度：
            float accelBrakeSensitivity = (desiredSpeed < m_CarController.CurrentSpeed)
                                              ? m_BrakeSensitivity
                                              : m_AccelSensitivity;

            // 确定实际的刹车/刹车输入量，以达到预期的速度。
            float accel = Mathf.Clamp((desiredSpeed - m_CarController.CurrentSpeed) * accelBrakeSensitivity, -1, 1);

            // 添加加速“漫游”，这也可以防止人工智能在驾驶中显得过于统一和机械
            // I.E.增加雅各车的行驶量会在比赛中导致赛车之间的碰撞和颠簸
            accel *= (1 - m_AccelWanderAmount) +
                     (Mathf.PerlinNoise(Time.time * m_AccelWanderSpeed, m_RandomPerlin) * m_AccelWanderAmount);

            // 计算目标的相对位置，以转向
            Vector3 localTarget = transform.InverseTransformPoint(offsetTargetPos);

            // 计算出目标的局部角度
            float targetAngle = Mathf.Atan2(localTarget.x, localTarget.z) * Mathf.Rad2Deg;

            // 获得将汽车瞄准目标所需的转向量
            float steer = Mathf.Clamp(targetAngle * m_SteerSensitivity, -1, 1) * Mathf.Sign(m_CarController.CurrentSpeed);

            //输入到汽车控制器。
            m_CarController.Move(steer, accel, accel, 0f);

            // 如果合适的话，当我们离目标很近的时候就别再开车了。
            if (m_StopWhenTargetReached && localTarget.magnitude < m_ReachTargetThreshold)
            {
                m_Driving = false;
            }
        }
    }



    //一个碰撞器或刚体触动另一个刚体或碰撞器，在每帧都会调用OnCollisionStay，直到它们之间离开不接触。  
    private void OnCollisionEnter(Collision col)
    {
        //碰撞后速度减速到零
        m_Driving = false;
        // && m_CarController.CurrentSpeed < m_CarController.TopSpeed*0.8f
        if (col.rigidbody != null && m_CarController.CurrentSpeed < m_CarController.TopSpeed * 0.9f)
        {
            var otherAI = col.rigidbody.GetComponent<CarAIControl>();
            if (otherAI != null)
            {
                otherAI.m_Target = null;
                m_Target = null;
            }
        }
    }


    public void SetTarget(Transform target)
    {
        m_Target = target;
        m_Driving = true;
    }
}
